約 2,416,893 件
https://w.atwiki.jp/bambooflow/pages/62.html
ビットアクセス ビット結合 4ビット幅の変数を4つ結合する場合 sc_uint 4 a, b, c, d; sc_uint 16 z; z = ( a, b, c, d ); ビット選択 16ビット幅のを4ビットごと分割する例 sc_uint 16 a; sc_uint 4 w, x, y, z; w = a.range( 15, 12 ); x = a.range( 11, 8 ); y = a.range( 7, 4 ); z = a.range( 3, 0 ); または、 sc_uint 16 a; sc_uint 4 w, x, y, z; ( w, x, y, z ) = a; 1ビット拡張 SystemCでビット拡張はない?みたいなので、ちょっと亜流な例 sc_uint 1 flg; sc_uint 16 z, a; z = a ^ (sc_uint 16 )( (sc_int 1 )flg );
https://w.atwiki.jp/bambooflow/pages/160.html
SCVとは SCVとは? SCVでなにができる? SCVとは? SCVはSystemC Verification Standardの略。 SystemC検証のための拡張クラスライブラリ。 Socデザインのためのテストベンチと検証IPを開発するために提供されている。 Cadence社のTestBuilderとForte社のQuickBenchがベースらしい。 SCVでなにができる? トランザクション・ベース検証(Transaction-based Verification) データの内観(Data Introspection) ランダム生成、制限付ランダム(Constrained randamization)、重み付ランダム(Weighted randomization) トランザクション・レコーディング(Transaction Recording) スパース・アレイ(疎な配列, Spare Array) HDLシミュレータへの接続(PLI,VPI等を経由) カバレッジとアサーションはまだ無い。
https://w.atwiki.jp/systemc/pages/17.html
SystemCは、プログラム言語c++のライブラリなのでc++の理解が欠かせない。また、sc2veriのようなユーティリティも作りたい。SystemCではなくてc++に関する事項だと思う事柄は、ここに記述する。 boost研究
https://w.atwiki.jp/bambooflow/pages/166.html
SystemCのレポート処理 SystemCのレポート処理レポート使いかた1ー簡単な例 レポート使いかた2ー練習用すべてのメッセージを画面出力させたくないとき リファレンスsc_report_handlersc_actions sc_report メッセージの分類(レベル)一覧 メッセージ動作一覧デフォルトの動作 メッセージ表示用マクロ その他 SystemCのV2.1からレポート出力処理を簡単に制御するためのエラーレポートシステムが標準化されています。 エラーメッセージやトラッキングレポートなど発生元の特定し、デバッグを容易にすることは不可欠です。 メッセージには、Information、Warning、Error、Fatalの4つの種類があるようです。 この4つのメッセージについて出力方法を指定したり、動作を指定したりすることができます。 画面出力やログ出力を簡単に切り替えることができます。 簡単にメモ書きを残します。 レポート使いかた1ー簡単な例 以下に簡単な例を紹介。 サンプル #include systemc.h const char* sim_name = "test"; // メッセージID名 int sc_main( int argc, char* argv[] ) { sc_report_handler set_log_file_name("sample_run.log"); // ログファイル設定 sc_report_handler stop_after( SC_ERROR, 100 ); // シミュレーション終了指定 sc_report_handler set_actions( sim_name, SC_INFO, SC_DISPLAY | SC_LOG ); // 動作指定 SC_REPORT_INFO( sim_name, "sample report1" ); sc_start( 100, SC_NS ); SC_REPORT_INFO( sim_name, "sample report2" ); return 0; } set_log_file_nameはメッセージを出力するレポートファイル名を指定します。 どこで、そのメッセージが出力されているかのグループ分けのために使用します。 とりあえずはファイル名やモジュール名等を指定するとよいかもしれません。 stop_afterはレポート情報の回数からシミュレーションを停止するタイミングを指定することができます。stop_after( SC_ERROR, 100 )は「ERROR(エラー)」レベルのメッセージの数(SC_REPORT_ERRORの実行回数)が100回となったらシミュレーションを停止させます。ゼロに設定するとdisableです。 今回のサンプルでは意味ないです。 set_actionsはメッセージ処理に対する動作を設定することができます。et_actions( sim_name, SC_INFO, SC_DISPLAY | SC_LOG )は、「INFO(情報)」レベルのメッセージを画面出力とファイル出力に設定しています。 画面表示 Info test sample report1 Info test sample report2 標準出力(std cout)にレポートを出力するにはset_actionsでSC_DISPLAYを設定します。 レポートファイル出力(sample_run.log) 0 s Info test sample report2 100 ns Info test sample report2 ファイルに出力するには、set_log_file_nameにて出力ファイル名を設定して、かつ、set_actionsにてSC_LOGを設定します。 ファイルへの出力には経過時間も記録されるみたいです。 デフォルトの動作はすべてのメッセージレベルはログ出力となっているので、ログファイル指定するだけで出力されるはずです。 レポート使いかた2ー練習用 いろいろ試してみました。 以下にサンプルコードを載せます。実際に使うときはもっときれいに書きたいものです。 このサンプルは、レポート処理の動作を見るために作ったものです。 モジュールはMOD1とMOD2があります。 モジュールはそれぞれスレッドを持っていて、定期的にメッセージを出力させています。 メッセージの制御は、sc_mainで行います。 はじめの状態は、単にデフォルト設定のままで、ログファイル("sample_run.log")出力するだけです。 コメントアウトされているsc_actionsやsc_stop_afterを有効にすることでメッセージ制御が行えます。 サンプルコード(sample_report02.cpp) #include systemc.h const char* id_name1 = "ID_1"; const char* id_name2 = "ID_2"; SC_MODULE( MOD1 ) { SC_CTOR( MOD1 ) { SC_THREAD( thread ); } void thread() { int cnt = 0; while (true) { ++cnt; wait( 10, SC_NS ); if (cnt%80==0) SC_REPORT_FATAL( id_name1, "sample Fatal1" ); else if (cnt%50==0) SC_REPORT_ERROR( id_name1, "sample Error1" ); else if (cnt%30==0) SC_REPORT_WARNING( id_name1, "sample Warning1" ); else if (cnt%10==0) SC_REPORT_INFO( id_name1, "sample Info1" ); } } }; SC_MODULE( MOD2 ) { SC_CTOR( MOD2 ) { SC_THREAD( thread ); } void thread() { int cnt = 0; while (true) { ++cnt; wait( 15, SC_NS ); if (cnt%100==0) SC_REPORT_FATAL( id_name2, "sample Fatal1" ); else if (cnt%70==0) SC_REPORT_ERROR( id_name2, "sample Error1" ); else if (cnt%40==0) SC_REPORT_WARNING( id_name2, "sample Warning1" ); else if (cnt%20==0) SC_REPORT_INFO( id_name2, "sample Info1" ); } } }; int sc_main( int argc, char* argv[] ) { MOD1 mod1("mod1"); MOD2 mod2("mod2"); // 以下、メッセージの制御 sc_report_handler set_log_file_name("sample_run.log"); //sc_report_handler set_actions( SC_ERROR, SC_DISPLAY | SC_LOG | SC_CACHE_REPORT ); //sc_report_handler set_actions( SC_FATAL, SC_DISPLAY | SC_LOG | SC_CACHE_REPORT ); //sc_report_handler suppress( SC_THROW ); //sc_report_handler stop_after( SC_FATAL, 10 ); //sc_report_handler set_actions( SC_INFO, SC_DISPLAY | SC_LOG ); //sc_report_handler stop_after( SC_FATAL, 10 ); //sc_report_handler stop_after( SC_ERROR, 10 ); //sc_report_handler set_actions( id_name1, SC_WARNING, SC_LOG | SC_CACHE_REPORT ); // シミュレーション実行 sc_start( 1., SC_MS ); // シミュレーション終了後の処理 cout endl; cout " ****** end-time = " sc_time_stamp() " ******" endl; cout endl; sc_report *rp = sc_report_handler get_cached_report(); if (rp) { cout "--- Cache Messgage ---" endl; cout rp- get_msg() endl; cout "--- Cache Messgage end ---" endl; } cout endl; cout "--- " id_name1 " ---" endl; cout " Info count = " sc_report_handler get_count( id_name1, SC_INFO ) endl; cout " Warning count = " sc_report_handler get_count( id_name1, SC_WARNING ) endl; cout " Error count = " sc_report_handler get_count( id_name1, SC_ERROR ) endl; cout " Fatal count = " sc_report_handler get_count( id_name1, SC_FATAL ) endl; cout "--- " id_name2 " ---" endl; cout " Info count = " sc_report_handler get_count( id_name2, SC_INFO ) endl; cout " Warning count = " sc_report_handler get_count( id_name2, SC_WARNING ) endl; cout " Error count = " sc_report_handler get_count( id_name2, SC_ERROR ) endl; cout " Fatal count = " sc_report_handler get_count( id_name2, SC_FATAL ) endl; cout "--- TOTAL ---" endl; cout " Info count = " sc_report_handler get_count( SC_INFO ) endl; cout " Warning count = " sc_report_handler get_count( SC_WARNING ) endl; cout " Error count = " sc_report_handler get_count( SC_ERROR ) endl; cout " Fatal count = " sc_report_handler get_count( SC_FATAL ) endl; return 0; } 画面出力例 ・・・ Error ID_1 sample Error1 In file report_sample02.cpp 15 In process mod1.thread @ 500 ns ****** end-time = 500 ns ****** --- Cache Messgage --- sample Error1 --- Cache Messgage end --- --- ID_1 --- Info count = 3 Warning count = 1 Error count = 1 Fatal count = 0 --- ID_2 --- Info count = 1 Warning count = 0 Error count = 0 Fatal count = 0 --- TOTAL --- Info count = 4 Warning count = 1 Error count = 1 Fatal count = 0 デフォルトのレポートの動作では、エラーメッセージが表示されると、throwへとばされて、シミュレーションが終了してしまいます。 通常ならば、エラーが出力された時点でシミュレーションが止まっても問題ないと思いますが、継続して実行したい場合もあります。 その時は、以下のような設定をします。 sc_report_handler set_actions( SC_ERROR, SC_DISPLAY | SC_LOG | SC_CACHE_REPORT ); // SC_THROWをはずす SC_ERRORの動作をデフォルト設定から上書きします。 ためしに設定を有効にして実行してみます。 実行結果 ・・・ Fatal ID_1 sample Fatal1 In file report_sample02.cpp 15 In process mod1.thread @ 800 ns アボートしました 今度は、Fatalメッセージが出力されると同時に、アボートしてしまいました。 これは、Fatalのデフォルト設定にSC_ABORTが設定されているためです。 先ほどのERROR同様に、SC_ABORTをはずして設定を上書きすれば止まらなくなります。 sc_report_handler set_actions( SC_ERROR, SC_DISPLAY | SC_LOG | SC_CACHE_REPORT ); // SC_ABORTをはずす 設定して、実行するとシミュレーションは1ms(sc_startに設定した時間)経過して止まると思います。 今度は、FATALメッセージが10回表示されたら、シミュレーションを終了するようにします。 設定は以下を追加します。 sc_report_handler stop_after( SC_FATAL, 10 ); 設定して実行すると、TOTALのFatal count値が10でシミュレーションが終了すると思います。 stop_afterは、IDを指定することもできます。 sc_report_handler stop_after( id_name2, SC_FATAL, 10 ); // id_name2="ID_2" 上記の設定にして実行すると、ID_2のFATALメッセージが10回表示された時点でシミュレーションが終了すると思います。 すべてのメッセージを画面出力させたくないとき すべてのメッセージを画面出力させたくないときは、以下を設定します。 sc_report_handler suppress( SC_DISPLAY ); 解除するときは、suppress()を実行すればよいようです。 逆に強制的に画面出力させるときは、force( SC_DISPLAY )とすればよいようです。 リファレンス sc_report_handler 次を参照してください。 sc_report_handler sc_actions メッセージに対して動作を指定することができます。 static sc_actions set_actions( sc_severity, sc_actions = SC_UNSPECIFIED ); メッセージレベルごとに動作を指定します。 static sc_actions set_actions( const char* msg_type, sc_actions = SC_UNSPECIFIED ); IDごとに動作を指定します。 static sc_actions set_actions( const char* msg_type, sc_severity, sc_actions = SC_UNSPECIFIED ); メッセージレベルとIDごとに動作を指定します。 sc_report 次を参照してください。 sc_report メッセージの分類(レベル)一覧 メッセージには以下のような種類があります。 sc_severity SC_INFO 情報出力 SC_WARNING 警告、問題かもしれないことを知らせる SC_ERROR 重大な問題 SC_FATAL 致命的な問題、デフォルトではシミュレーションを終了 メッセージ動作一覧 メッセージのレベルごとに動作を指定することができます。 enum SC_UNSPECIFIED SC_DO_NOTHING 何もしない SC_THROW レポートとの内容に対応するC++の例外を発生。 SC_LOG レポートをログに出力する。通常はディスク上のファイルへ出力。 SC_DISPLAY レポートを画面出。 SC_INTERRUPT シミュレーションを一時停止。sc_interrupt_hereをよぶ。 SC_CACHE_REPORT レポートのコピーを保存。get_cached_repot()より後に取得できる。 SC_STOP sc_stop()をよぶ。 SC_ABORT sc_abort()をよぶ。 デフォルトの動作 デフォルトの動作は次のように設定されているようです。 SC_DEFAULT_INFO_ACTIONS (SC_LOG | SC_DISPLAY) SC_DEFAULT_WARNING_ACTIONS (SC_LOG | SC_DISPLAY) SC_DEFAULT_ERROR_ACTIONS (SC_LOG | SC_CACHE_REPORT | SC_THROW) SC_DEFAULT_FATAL_ACTIONS (SC_LOG | SC_DISPLAY | SC_CACHE_REPORT | SC_ABORT) 全てのメッセージは(ログファイル名が設定されていれば)ファイル出力します。 FATAL時、シミュレーションはアボートします。 メッセージ表示用マクロ SC_REPORT_INFO(id,msg) 情報メッセージに使用 SC_REPORT_WARNING(id,msg) ワーニングメッセージに使用 SC_REPORT_ERROR(id,msg) エラーメッセージに使用 SC_REPORT_FATAL(id,msg) 致命的エラーメッセージに使用 sc_assert(expr) アサート、assertのかわりに使用 sc_assertは以下のようにdefine定義されています。 #define sc_assert(expr) \ ((void) ((expr) ? 0 (SC_REPORT_FATAL( SC_ID_ASSERTION_FAILED_ , #expr ), 0))) その他 SystemCのログファイルからVCDファイルを生成するツールを作ってみました。 てきとうなので、うまくうごかなかったらごめんなさい。 sysclog2vcd.pl 使いかた % ./sysclog2vcd.pl ログファイル名 % gtkwave sysclog.vcd 以上
https://w.atwiki.jp/bambooflow/pages/164.html
SytemCで固定小数点 固定小数点の使い方についてメモしておく。 忘れっぽいので。。。 IEEE1666のLRMを見るとグラフつきでわかりやすいかも。 SytemCで固定小数点 種類 テンプレート・パラメータ量子化モード(誤差)SC_RND SC_RND_ZERO SC_RND_MIN_INF SC_RND_INF SC_RND_CONV SC_TRN (デフォルト) SC_TRN_ZERO オーバーフローモードSC_SAT SC_SAT_ZERO SC_SAT_SYM SC_WRAP (デフォルト) SC_WRAP_SM 固定小数点のコンパイル 使い方例オーバーフロー有無の確認 固定小数点 == sc_uint変換 種類 符号付固定小数点sc_dt sc_fixed W, I, Q, O, N 符号なし固定小数点sc_dt sc_ufixed W, I, Q, O, N よく使うのは、sc_fixed、sc_ufixedの2つだけ。 他はあまり使わない。。。 高速版、符号付固定小数点sc_dt sc_fixed_fast W, I, Q, O, N 高速版、符号なし固定小数点sc_dt sc_ufixed_fast W, I, Q, O, N 高速版は、32ビットOSにおいて、途中の計算を53ビットに制限して(double)高速化を実現しているらしい。 精度は落ちるかもしれないので、よく検討するべし。 動的サイズ:符号付固定小数点sc_dt sc_fix 動的サイズ:符号なし固定小数点sc_dt sc_ufix 動的サイズ、高速版:符号付固定小数点sc_dt sc_fix_fast 動的サイズ、高速版:符号なし固定小数点sc_dt sc_ufix_fast sc_fixed(テンプレート型)とsc_fix(テンプレート型)の違いがある。 テンプレート・パラメータ パラメータ 値の型 説明 W int(正の値) 全体のビット幅(ワード長) I int 整数部のビット幅、正負の値が指定できる Q sc_q_mode 量子化モード(省略可) O sc_o_mode オーバーフローモード(省略可) N int オーバーフロー用ビット数(省略可、Oのためのオプション) 量子化モード(誤差) 第3番目のパラメータで丸め方向を決めることができる。 sc_q_mode SC_RND 正の無限方向への丸め SC_RND_ZERO ゼロ方向への丸め SC_RND_MIN_INF 負の無限方向への丸め SC_RND_INF 無限方向への丸め SC_RND_CONV 収束丸め SC_TRN(デフォルト) 切捨て SC_TRN_ZERO ゼロ方向へ切捨て SC_RND 正の方向への丸め (rounding to plus infinity) 例) y = sc_fixed 3,2,SC_RND (x); 代入前[ x ] 代入後[ y ] -側 0b10.11 (-1.25) 0b11.0 (-1.0) +側 0b01.01 ( 1.25) 0b01.1 ( 1.5) LSB-1番目のビットが、1ならば上へ、0ならば下へ。 SC_RND_ZERO ゼロ方向への丸め (rounding to zero) 例) y = sc_fixed 3,2,SC_RND_ZERO (x); 代入前[ x ] 代入後[ y ] -側 0b10.11 (-1.25) 0b11.0 (-1.0) +側 0b01.01 ( 1.25) 0b01.0 ( 1.0) SC_RND_MIN_INF マイナス方向への丸め (rounding to minus infinity) 例) y = sc_fixed 3,2,SC_RND_MIN_ZERO (x); 代入前[ x ] 代入後[ y ] -側 0b10.11 (-1.25) 0b10.1 (-1.5) +側 0b01.01 ( 1.25) 0b01.0 ( 1.0) SC_RND_INF 無限方向への丸め (rounding to infinity) 例) y = sc_fixed 3,2,SC_RND_ZERO (x); 代入前[ x ] 代入後[ y ] -側 0b10.11 (-1.25) 0b10.1 (-1.5) +側 0b01.01 ( 1.25) 0b01.1 ( 1.5) SC_RND_CONV 収束丸め (convergent rounding) 例) y = sc_fixed 3,2,SC_RND_CONV (x); 代入前[ x ] 代入後[ y ] -側 0b10.11 (-1.25) 0b11.0 (-1.0) +側 0b01.01 ( 1.25) 0b01.0 ( 1.0) 0b10.11(-1.25) = x = 0b11.01(-0.75) y = 0b11.0(-1.0) 0b11.10(-0.75) x 0b11.11(-0.25) y = 0b11.1(-0.5) 0b11.10(-0.25) = x = 0b00.01( 0.25) y = 0b00.0( 0.0) 0b00.01( 0.25) x 0b00.11( 0.75) y = 0b00.0( 0.5) 0b00.11( 0.75) = x = 0b01.01( 1.25) y = 0b01.0( 1.0) ( =, =)と( , )とが交互。奇数と偶数とで異なる。 Convergent Roundingは特定の用途に用いられるらしい。 SC_TRN (デフォルト) 切捨て (truncation) 例) y = sc_fixed 3,2,SC_TRN (x); 代入前[ x ] 代入後[ y ] -側 0b10.11 (-1.25) 0b10.1 (-1.5) +側 0b01.01 ( 1.25) 0b01.0 ( 1.0) これは、デフォルト。 計算は切捨てなので高速だが、精度が出ない。 精度をあげるならば、SC_RNDを使う。 SC_TRN_ZERO ゼロ方向へ切捨て (truncation to zero) 例) y = sc_fixed 3,2,SC_TRN_ZERO (x); 代入前[ x ] 代入後[ y ] -側 0b10.11 (-1.25) 0b11.0 (-1.0) +側 0b01.01 ( 1.25) 0b01.0 ( 1.0) オーバーフローモード オーバーフローを起こした場合、4番目と5番目のパラメータにより調整することができる。 種類は、飽和もしくは折り返しがある。 sc_o_mode SC_SAT 単純飽和 SC_SAT_SYM 対称飽和 SC_SAT_ZERO ゼロ飽和 SC_WRAP(デフォルト) 折り返し SC_WRAP_SM sign magnitude折り返し 単純飽和は、最大値を超えたら最大値まで減少、最小値を下回ったら最小値まで増加させる。 対称飽和は、最大値側は単純飽和とおなじ。最小値を下回ったら"-最大値"まで増加させる。 ゼロ飽和は、オーバーフローを起こしたら、値をゼロにする。 折り返しは、収まらない上位ビットを削除。 パラメータNでを使用する。 SC_SAT 単純飽和 例) y = sc_fixed 3,3,SC_SAT (x) 代入前[ x ] 代入後[ y ] 備考 -側 -6 -4 オーバーフロー -5 -4 オーバーフロー -4 -4 -3 -3 -2 -2 -1 -1 0 0 1 1 2 2 3 3 4 3 オーバーフロー +側 5 3 オーバーフロー 上限よりも下限の飽和する絶対値は異なることに注意。 SC_SAT_ZERO ゼロ飽和 例) y = sc_fixed 3,3,SC_SAT_ZERO (x) 代入前[ x ] 代入後[ y ] 備考 -側 -6 0 オーバーフロー -5 0 オーバーフロー -4 -4 -3 -3 -2 -2 -1 -1 0 0 1 1 2 2 3 3 4 0 オーバーフロー +側 5 0 オーバーフロー オーバーフローすると、ゼロ値となる。 SC_SAT_SYM 対称飽和 例) y = sc_fixed 3,3,SC_SAT_SYM (x) 代入前[ x ] 代入後[ y ] 備考 -側 -6 -3 オーバーフロー -5 -3 オーバーフロー -4 -3 オーバーフロー -3 -3 -2 -2 -1 -1 0 0 1 1 2 2 3 3 4 3 オーバーフロー +側 5 3 オーバーフロー -側のオーバーフロー値は、+側の絶対値と同じとなる。 SC_WRAP (デフォルト) ラップアラウンド。~ n_bit=0 n_bit 0 SC_WRAP_SM 符号つき絶対値ラップアラウンド n_bits=0 n_bits 0 固定小数点のコンパイル SC_INCLUDE_FXをsystemc.hをインクルードする前に定義する必要がある。 これがないと、コンパイルが通らずエラーとなる。 #define SC_INCLUDE_FX #include "systemc.h" もしくは、コンパイル時に"-D"で指定する。 -DSC_INCLUDE_FX 関連 SC_FX_EXCLUDE_OTHER 使い方例 オーバーフロー有無の確認 sc_fixed 4,4 a(1.0); // ワード長4ビット,整数4ビット sc_fixed 4,4 b(1.0); sc_fixed 4,4 c(8.0); sc_fixed 4,4 d(8.0); sc_fixed 4,4 z; cout "o_flag = " z.overflow_flag() endl; z = a * b; // 1.0 x 1.0 = 1.0 オーバーフローなし cout "z = " z endl; cout "o_flag = " z.overflow_flag() endl; z = c * d; // 8.0 x 8.0 = 64.0 オーバーフロー発生 cout "z = " z endl; cout "o_flag = " z.overflow_flag() endl; 結果 o_flag = 0 z = 1 o_flag = 0 z = 0 o_flag = 1 = オーバーフロー発生を確認 固定小数点 == sc_uint変換 よさそうな方法が思いつかないので、とりあえず。 sc_fixed == sc_uint 変換 sc_fixed 4,2 1(1.25); // 1.25 (0b01.01) sc_uint 4 x, y; x = a; // 1.00 (0b00001), 整数部のみを代入 y = a.range( a.wl()-1, 0 ); // 5 (0b00101), ビット列を単純代入 sc_uint == sc_fixed 変換 sc_uint 4 a(5); // 5 (0b00101) sc_fixed 6,4 x; sc_fixed 4,2 y; x = a; // 5.00 (0b0101.00), 整数として代入 y.range( y.wl()-1, 0 ) = a; // 1.25 (0b01.01), ビット列を単純代入
https://w.atwiki.jp/bambooflow/pages/113.html
SystemCの検証環境モデル構成 SystemCの検証環境モデル構成1.小規模なモデルテストサンプルプログラム 2.中規模なモデルテストサンプルプログラム 3.大規模なモデルテストサンプルプログラム おそらく3.のモデル構成が多くに記述する形になる。 1.小規模なモデルテスト 比較的小さなモデルの検証をしたいときのモデル構成。 #ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (verif_model_s.png) sc_mainのところで、 検証モデルのオブジェクトを実体化 クロック信号を生成、接続 入出力信号の接続 テストパタン用意 シミュレーション時間の更新 必要があれば、テストパタン用意、時間更新を繰り返す。 をする。 メインとモデルの2ファイルで済む。 しかし、シミュレーションがしにくかったり拡張しにくかったりする。 サンプルプログラム template_s.tgz 階層構造 sc_main |== myModel(MyModel) MyModel機能クロックなし 4つの値を入力(in_a, in_b, in_c, in_d) 合計出力(out_total) 平均出力(out_ave) 最小値出力(out_min) 最大値出力(out_max) 2.中規模なモデルテスト モデルが複雑になり、テストパタンが大きくなったとき、 別にテストベンチを用意して検証を実施するようなモデル構成。 #ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (verif_model_m.png) sc_mainでは、 モデルの実体化 テストベンチの実体化 クロック信号生成、接続 モデル間信号接続 シミュレーション開始sc_start() をする。 シミュレーションの終了は、テストベンチのプロセス内にsc_stop()を入れて、必要なタイミングで終了するようにする。 テストモデルとテストベンチとメインで構成する。 メインプログラムに接続等を記述するので、環境を移動させるのが難がある。 サンプルプログラム template_clk_m.tgz 階層構造 sc_main |== myModel(MyModel) |== testBench(TestBench) MyModel機能クロック動作 4つの値を入力(in_a, in_b, in_c, in_d) 合計出力(out_total) 平均出力(out_ave) 最小値出力(out_min) 最大値出力(out_max) 3.大規模なモデルテスト 検証環境が複雑になったときのモデル構成。 テストベンチとモデルの上にトップモジュールをおく。 #ref error :ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (verif_model_l.png) sc_mainでは、 TOPモジュールの実体化 シミュレーション開始sc_start() TOPモジュールでは、 モデルの実体化 テストベンチの実体化 クロック信号生成、接続 モデル間信号接続 をする。 ファイルが多くなって複雑にみえるかもしれないが、一度覚えてしまえばモデル追加や検証するのが容易。 この形は、sc_mainで1つのオブジェクト(TOPモジュール)を実体化するだけで済むので、規模の小さいモデル構成でもはじめからこの形にしたほうがよい。 サンプルプログラム template_clk_l.tgz 階層構造 sc_main |== syscTop(SyscTop) |== myModel(MyModel) |== testBench(TestBench) MyModel機能クロック動作 4つの値を入力(in_a, in_b, in_c, in_d) 合計出力(out_total) 平均出力(out_ave) 最小値出力(out_min) 最大値出力(out_max)
https://w.atwiki.jp/bambooflow/pages/168.html
イベント イベント(sc_event)はスレッド間の同期をとるために非常に役立ちます。 ここでは、イベント(sc_event)の使い方についてメモします。 イベント sc_eventの使い方簡単なsc_event使用例 2つのスレッドがお互いに同期をとる記述例 誤った使い方 まとめ リファレンス sc_eventの使い方 簡単なsc_event使用例 以下にもっとも簡単なsc_eventの使い方を記述します。 #include systemc.h SC_MODULE( TOP ) { sc_event e0; // イベント準備 SC_CTOR( TOP ) { SC_THREAD( thread0 ); SC_THREAD( thread1 ); } // イベントを通知するスレッド void thread0() { cout "--- thread0 start ---" endl; while (true) { wait( 10, SC_NS ); e0.notify(); // イベント通知 } } // イベントを受け取るスレッド void thread1() { cout "--- thread1 start ---" endl; while (true) { wait( e0 ); // イベント待ち cout sc_time_stamp() " thread1" endl; } } }; int sc_main( int argc, char* argv[] ) { TOP top( "top" ); sc_start( 100, SC_NS ); return 0; } 実行結果 --- thread0 start --- --- thread1 start --- 10 ns thread1 20 ns thread1 30 ns thread1 40 ns thread1 50 ns thread1 60 ns thread1 70 ns thread1 80 ns thread1 90 ns thread1 とりあえずsc_eventの動作確認するだけなので、なんの面白みもないです。 あえて言うなら、こんな処理で2つスレッドを用意するのは無駄です。 説明のためにあえて2つのスレッドを用意しました。 イベントの用途は、基本はプロセス間の同期です。 記述を見ていきます。 まず、TOPモジュールのメンバ変数として、イベントe0を用意しています。 sc_evnet e0; thread0とthread1はSC_THREAD指定してwhile(true)文により無限ループとなっています。 thread0では、イベントを通知(発行)しています。 e0.notify(); thread1では、イベントを待っています。 wait( e0 ); イベントを受け取ると、ウェイト状態が解除され、waitの後述部分が処理されます。 後述は、ここでは単に標準出力(cout)させてます。 ようは、thread1の動作開始をthread0から操作しているようなイメージです。 今回はnotify()の引数はなにも与えていませんが、時間を指定することもできます。 たとえば、次のように記述できます。 e0.notify( 5, SC_NS ); このように記述すると、notifyが実行されてから5[ns]後にイベントが通知されることになります。 注意 プロセス間のタイミングを取るために通常の変数(boolやint)を使うのは誤りです。 プロセス間のタイミングでは、必ずsc_eventもしくはチャネル(sc_signal やsc_buffer )を使わないといけません。 そうしないと、シミュレーション誤動作の原因となります。 2つのスレッドがお互いに同期をとる記述例 #include systemc.h SC_MODULE( TOP ) { sc_event e0; // イベント宣言 sc_event e1; // イベント宣言 SC_CTOR( TOP ) { SC_THREAD( thread0 ); SC_THREAD( thread1 ); } void thread0() { cout "--- thread0 start ---" endl; wait( SC_ZERO_TIME ); while (true) { e0.notify(); // イベント通知 wait( e1 ); // イベントを待つ cout sc_time_stamp() " thread0" endl; wait( 10, SC_NS ); } } void thread1() { cout "--- thread1 start ---" endl; while (true) { wait( e0 ); // イベントを待つ cout sc_time_stamp() " thread1" endl; wait( 10, SC_NS ); e1.notify(); // イベント通知 } } }; int sc_main( int argc, char* argv[] ) { TOP top( "top" ); sc_start( 100, SC_NS ); return 0; } 実行結果 --- thread0 start --- --- thread1 start --- 0 s thread1 10 ns thread0 20 ns thread1 30 ns thread0 40 ns thread1 50 ns thread0 60 ns thread1 70 ns thread0 80 ns thread1 90 ns thread0 実行結果をみると、thread0とthread1が交互に動作していることがわかります。 thread0は、イベント通知→イベント待ち→標準出力→wait(10ns)、 thread1は、イベント待ち→標準出力→wait(10ns)→イベント通知、 の順番となっています。 ここで、1点注目してほしいのは、thread0のwhile(true)文の前で、waitを1回呼んでいることです。 wait( SC_ZERO_TIME ); これは、必要です。 なぜならば、イベントの発生を知るためにはそのイベントを常に監視していなければならない、というルールがあるからです。 もし、このwait記述がないと正しく動作してくれません。でも動作することもあります。あいまいです。 それは、最初の動作時にthread0のe0.notify()とthread1のwait(e0)のどちらが先に実行されるかがあいまいだからです。 thread1のwait(e0)が先に実行されれば所望の動作しますが、thread0のe0.notify()が先に実行されてしまうと、イベント発行を見逃してしまうことになります。 誤った使い方 1つのスレッド内で使おうとした例 次の記述は明らかに誤りです。 SC_MODULE( TOP ) { sc_event m_evnt; SC_CTOR( TOP ) { SC_THREAD( thread0 ); } void thread0 { while (true) { m_evnt.notify(); /* ... */ wait( m_evnt ); } } }; m_evnt.notify()にてイベントを発行していますが、それを受けるwaitの位置がおかしいです。 本来であれば別プロセスにwaitを用意しなければいけません。 まとめ イベントは、2つのプロセスの同期をとるためのもの。 ルールとして、イベントは常に監視しなければ、イベント発行を見逃してしまう。 リファレンス sc_evnet
https://w.atwiki.jp/systemc/
来場者数 = - ここには、SystemCを利用する人のためのメモを置きます。個々のメモへは、左のメモよりお進みください。 メモを新規作成された方は、暫定メニューを編集してそのメモへのリンクを追加してください。ただし、SystemCと関係ない話題は削除されますので、メモとして登録しないで下さい。また、各社の機密営業情報は記述しないで下さい。疑わしい記述は削除しますので、企業情報には出典をできるだけ明記してください。 @wikiへようこそ ウィキはみんなで気軽にホームページ編集できるツールです。 このページは自由に編集することができます。 メールで送られてきたパスワードを用いてログインすることで、各種変更(サイト名、トップページ、メンバー管理、サイドページ、デザイン、ページ管理、等)することができます まずはこちらをご覧ください。 @wikiの基本操作 用途別のオススメ機能紹介 @wikiの設定/管理 分からないことは? @wiki ご利用ガイド よくある質問 無料で会員登録できるSNS内の@wiki助け合いコミュニティ @wiki更新情報 @wikiへのお問合せフォーム 等をご活用ください @wiki助け合いコミュニティの掲示板スレッド一覧 #atfb_bbs_list その他お勧めサービスについて 大容量1G、PHP/CGI、MySQL、FTPが使える無料ホームページは@PAGES 無料ブログ作成は@WORDをご利用ください 2ch型の無料掲示板は@chsをご利用ください フォーラム型の無料掲示板は@bbをご利用ください お絵かき掲示板は@paintをご利用ください その他の無料掲示板は@bbsをご利用ください 無料ソーシャルプロフィールサービス @flabo(アットフラボ) おすすめ機能 気になるニュースをチェック 関連するブログ一覧を表示 その他にもいろいろな機能満載!! @wikiプラグイン @wiki便利ツール @wiki構文 @wikiプラグイン一覧 まとめサイト作成支援ツール バグ・不具合を見つけたら? 要望がある場合は? お手数ですが、メールでお問い合わせください。
https://w.atwiki.jp/bambooflow/pages/147.html
サンプル --シンプルFIFO-- systemcのディレクトリにexamplesがあって、その中のsimple_fifoをみてみた。 これは、おおよそsc_fifoを自分で作るようなサンプルとなっているようだ(若干簡単にしている)。 このサンプルが理解できればsc_fifoの動作もわかるようだ。 インターフェース、チャネル、ポートの関係はSystemCを理解する上でかなり重要なところ。 サンプル --シンプルFIFO--simple_fifoサンプル場所 FIFO作成について インターフェースとチャネルの関係 インターフェースとチャネルとポートの接続関係 インターフェース作成出力側インターフェース(write_if) 入力側インターフェース(read_if) チャネル作成(fifo) writeとreadのブロッキング動作 ポート作成、接続、アクセス送信側[producer](sc_port write_if ) 受信側[consumer](sc_port read_if ) トップ接続 write,read動作説明 まとめ simple_fifoサンプル場所 SystemCのパッケージを展開した以下の場所。 systemc-2.2.0/examples/sysc/simple_fifo/ FIFO作成について このサンプルで作成するFIFOは階層チャネルになる(sc_channelを継承する)。 通信に必要なものはつぎのとおり。 インターフェース(write_if, read_if) チャネル(fifo) また、送受信するモジュールはポート(sc_port write_if , sc_port read_if )を準備する必要がある。 インターフェースとチャネルの関係 クラス図 sc_interface ↑ ┌──┴──┐ write_if read_if ↑ ↑ sc_channel └──┬──┘ ↑ ├────────┘ │ fifo インターフェースとチャネルとポートの接続関係 《送信側》 《受信側》 sc_port write_if ==== fifo ==== sc_port read_if インターフェース作成 インターフェースは次の2つのルールで作成する。 sc_interfaceを継承する 純粋仮想関数(virtual=0)のみをpublicで宣言する 出力側インターフェース(write_if) 値をFIFOへ書き込む側のインターフェース。 class write_if virtual public sc_interface { public virtual void write(char) = 0; virtual void reset() = 0; }; 出力側はwriteとresetメソッドを準備している。sc_fifoでは、ノンブロッキングで書き込むnb_writeメソッドやFIFOが満杯かどうか取得するためのnum_freeメソッドがあるが、このサンプルは最小限のものだけにしているようだ。 入力側インターフェース(read_if) 値をFIFOから取り出すインターフェース。 class read_if virtual public sc_interface { public virtual void read(char ) = 0; virtual int num_available() = 0; }; 入力側ではreadとnum_availableメソッドを準備している。num_availableはFIFOに溜っている数を返す。sc_fifoにあるnb_fifoメソッド等は宣言していない。 チャネル作成(fifo) class fifo public sc_channel, public write_if, public read_if { public fifo(sc_module_name name) sc_channel(name), num_elements(0), first(0) {} void write(char c) { wait(read_event); data[(first + num_elements) % max] = c; ++ num_elements; write_event.notify(); } void read(char c){ if (num_elements == 0) wait(write_event); c = data[first]; -- num_elements; first = (first + 1) % max; read_event.notify(); } void reset() { num_elements = first = 0; } private enum e { max = 10 }; char data[max]; int num_elements, first; sc_event write_event, read_event; チャネルfifoはインターフェースであるwrite_ifとread_if、ならびにsc_channelを継承する。 そして、write_ifとread_ifを継承したので、インターフェースの純粋仮想関数の中身を書く必要がある。 このチャネルのFIFO数は、最大10個固定のようだ。(sc_fifoの場合は、コンストラクタの第2引数にFIFO数を設定できる) writeとreadのブロッキング動作 fifoに記述されたwrite、readメソッドはwait()が含まれているのでブロッキング・メソッドである。 writeの動作は、FIFOが満杯のとき、送信側の処理を一時停止する。 readの動作は、FIFOが空のとき、受信側の処理を一時停止する。 以下にwriteとreadのブロッキング動作を説明するために必要な部分を抜き出してみた。 sc_event write_event, read_event; int num_elements; void write(char c) { if (num_elements == max) wait(read_event); // FIFOが満杯のとき、readイベント通知を待つ ++ num_elements; write_event.notify(); // writeイベントを通知する } void read(char c){ if (num_elements == 0) wait(write_event); // FIFOが空のとき、writeイベント通知を待つ -- num_elements; read_event.notify(); // readイベントを通知する } write側では、readイベントを待ち、writeイベントを通知する。 read側では、writeイベントを待ち、readイベントを通知する。 この処理では時間概念はない。デルタ遅延で処理される。 ポート作成、接続、アクセス 送信側[producer](sc_port write_if ) producerモジュール記述を部分的に抜粋 class producer public sc_module { public sc_port write_if out; // ポート作成 ... void main() // SC_THREAD { ... while (*str) out- write(*str++); // writeアクセス } }; インターフェースwrite_ifのAPIにアクセスするためには"- "を使う。 writeを呼ぶと、実際にはfifoチャネルのwriteが呼ぶことになる。 受信側[consumer](sc_port read_if ) consumerモジュール記述を部分的に抜粋 class consumer public sc_module { public sc_port read_if in; // ポート作成 ... void main() // SC_THREAD { while (true) { in- read(c); // readアクセス } } }; インターフェースread_ifのAPIにアクセスするためには"- "を使う。 readを呼ぶと、実際にはfifoチャネルのreadが呼ぶことになる。 トップ接続 class top public sc_module { public fifo *fifo_inst; producer *prod_inst; consumer *cons_inst; top(sc_module_name name) sc_module(name) { fifo_inst = new fifo("Fifo1"); prod_inst = new producer("Producer1"); prod_inst- out(*fifo_inst); cons_inst = new consumer("Consumer1"); cons_inst- in(*fifo_inst); } }; 接続はsc_fifoやsc_signalのやりかたと変わらない。 モジュール- ポート( チャネル ) write,read動作説明 シミュレーションが開始されると、prod_inst(producer)とcons_inst(consumer)のプロセスが同時に処理を始める。 はじめに、cons_inst側のプロセスが動作したとすると、readが呼ばれ、FIFO数がゼロのためwaitで一時停止する。 (*1) 次に、prod_inst側のプロセスが動作をはじめ、writeが呼ばれる。 writeはFIFOが満杯になるまで繰り返し、満杯(10回書込み)になるとwait()で一時停止する。 このとき、writeイベントを(何度か)通知する。 (*2) const_inst側のプロセスでwriteイベントの通知を受けることで、動作を再開する。 FIFOはゼロでないので、ゼロになるまでreadを繰り返す。 FIFOがゼロになるとread内のwait()で一時停止する。 このとき、readイベントを(何度か)通知する。 (*3) 繰り返し ・・・ まとめ インターフェースとチャネルとポートの関係はSystemCの特徴の1つ。 SystemCでTLMを覚える一歩は、このsimple_fifoの動作を理解することから始まると思う。
https://w.atwiki.jp/bambooflow/pages/123.html
SystemC TLM-2.0について SystemC TLM-2.0についてはじめに背景 TLM-2.0で重視されていること TLMへの要求 TLM-2コーディングスタイルLoosely-timed(LT) Approximately-timed(AT) TLM-2.0正式版の機能テンポラルデカップリング(Temporal Decoupling) Direct Memory Interface(DMI) TLMインタフェースtlm_fw_transport_if<>(ターゲット側I/F) tlm_bw_transport_if<>(イニシエータ側I/F) インタフェースコールb_transport(FW) nb_transport_fw(FW) nb_transport_bw(BW) get_direct_mem_ptr(FW) invalidate_direct_mem_ptr(FW,BW) transport_dbg(FW) ソケット TLM-2.0クラスについて ジェネリック・ペイロードについて b_transportについて はじめに 背景 TLM-1標準では、トランザクション通信のためのコア・インタフェース群を定義した。 このインタフェース群はいくつかのアプリケーションにおいて成功したものの、メモリ・マップ バスのモデリングと他のon-chip通信ネットワークの観点3つの欠点を持つ。 TLM-1は標準トランザクションを持たない TLM-1はタイミング・アノテーションをサポートしない TLM-1インタフェースは全てのトランザクション・オブジェクトとデータを要求し、シミュレーションが低速となる。若干のアプリケーションはトランザクションオブジェクトで組込形ポインタでこの制約上で動くが、これは標準ではなくそして共通性がない。TLM-2はライフタイムがいくつかのトランスポート・コールで受け渡すトランザクションオブジェクトでこの欠点についてたいしょした。新しい通信インタフェースによりサポートした。 TLM-2では、 共通のトランザクション、ジェネリック・ペイロードが用意された テンポラル・デカップリング、ウォンタム・キーパーが用意された バックドア(DMI)が用意された TLM-2.0で重視されていること シミュレーション速度 インターオペラビリティ(モデルの共通したインタフェース、モデルの接続性の向上) TLMへの要求 ソフトウェア解析 ソフトウェア・パフォーマンス アーキテクチャ解析 ハードウェア検証 TLM-2コーディングスタイル TLM2.0Draft2まで次の3つがあった Un-Timed(UT) -- TLM-2.0正式版でLTに合わせられた Loosely-timed(LT) Approximately-timed(AT) TLM-2.0正式版は2つのコーディングスタイルとなっている Loosely-timed(LT) Approximately-timed(AT) Loosely-timed(LT) O/S起動とマルチコアシステム実行のための十分なタイミング精度 プロセスはシミュレーション時間の前に実行可能(テンポラル・デカップリング) 各トランザクションは開始と終了の2つのタイミング・ポイントを持つ ダイレクト・メモリ・インターフェース(DMI)の使用 b_transport(推奨) nb_transport Loosely おおまか Approximately-timed(AT) 別名、cycle-approximate(サイクル-アプロクシメイト)、または、cycle-count-accurate(サイクル-カウント-アキュレート) アーキテクチャの調査に十分な精度 プロセスはシミュレーション時間と横並びに実行 各トランザクションは4つのタイミング・ポイントを持つ(拡張可能) nb_transport_fw、nb_transport_bw Approximately おおよそ TLM-2.0正式版の機能 テンポラルデカップリング(Temporal Decoupling) wait()関数コールを少なくして、シミュレーション高速化を図る仕組み LTモデリングで採用 イニシエータもしくはターゲットでおおよその処理遅延を計算する b_transportもしくは、nb_transportによりトランザクションと一緒に処理遅延を渡し、あるタイミングでシミュレーション時間を更新する方法 Direct Memory Interface(DMI) トランザクションを発生させないで実メモリアドレスを直接取得する方法 SW検証環境向けに高速化を図るために有効 TLMインタフェース 次の2つのI/Fが使えれば、TLM-2.0はとりあえずOKかも。 ターゲットモデルはフォワード(FW)インタフェースを継承する(tlm_fw_transport_if ) イニシエータはバックワード(BW)インタフェースを継承する(tlm_bw_transport_if ) バスモデルは両方のインターフェースを継承する tlm_fw_transport_if<>(ターゲット側I/F) 次のクラスを継承している。 tlm_blocking_transport_if<> tlm_fw_nonblocking_transport_if<> tlm_fw_direct_mem_if<> tlm_transport_dbg_if<> 次は純粋仮想関数。 void b_transport (TRANS trans, sc_core sc_time t) tlm_sync_enum nb_transport_fw (TRANS trans, PHASE phase, sc_core sc_time t) bool get_direct_mem_ptr (TRANS trans, tlm_dmi dmi_data) unsigned int transport_dbg (TRANS trans) よって、tlm_fw_transport_ifを使用する場合は、最低でも上記4つの関数を定義する必要がある。 tlm_bw_transport_if<>(イニシエータ側I/F) 次のクラスを継承している。 tlm_bw_nonblocking_transport_if<> tlm_bw_direct_mem_if 次は純粋仮想関数。 tlm_sync_enum nb_transport_bw (TRANS trans, PHASE phase, sc_core sc_time t) void invalidate_direct_mem_ptr (sc_dt uint64 start_range, sc_dt uint64 end_range) よって、tlm_bw_transport_ifを使用する場合は、最低でも上記2つの関数を定義する必要がある。 インタフェースコール b_transport(FW) void b_transport (TRANS trans, sc_core sc_time t) イニシエータからターゲットにデータ転送(ブロッキング) TRANSは通常tlm_generic_payload tはタイミングアノテーション nb_transport_fw(FW) tlm_sync_enum nb_transport_fw (TRANS trans, PHASE phase, sc_core sc_time t) イニシエータからターゲットにデータ転送(ノン・ブロッキング) TRANSは通常tlm_generic_payload PHASEはtlm_phase、処理状況のフェーズ tはタイミングアノテーション nb_transport_bw(BW) tlm_sync_enum nb_transport_bw (TRANS trans, PHASE phase, sc_core sc_time t) ターゲットからイニシエータに対して処理状況を通知(ノン・ブロッキング) get_direct_mem_ptr(FW) bool get_direct_mem_ptr (TRANS trans, tlm_dmi dmi_data) 直接メモリの中身をイニシエータから読み書きするためのI/F(DMI) イニシエータからターゲットのじメモリのポインタを取得 トランザクションを介さない、通常の手続きとは異なるデータのやりとり サポートしない場合はfalseを返す invalidate_direct_mem_ptr(FW,BW) void invalidate_direct_mem_ptr (sc_dt uint64 start_range, sc_dt uint64 end_range) イニシエータ側にターゲットのメモリマップのポインタが使用不可能な状況になっていることを通知する DMI用関数 transport_dbg(FW) デバッグ用I/F Read/Write等の処理を行わないでデータを取得する イニシエータからターゲットの関数を呼ぶ サポートしない場合には、0を返す ソケット ソケットはイニシエータ - ターゲット間を通信するためのポート。sc_portとsc_exportをまとめたもにに近い。 インタフェースコールはソケットを介して使用する。 ソケットはすでにいくつか用意されているが、自分専用のソケットを作成してもOK。 tlm_utilsにConvenience socketsとしていくつか用意されている。 基本ソケットtlm_initiator_socket<BUSWIDTH, TYPES, N, POL> tlm_target_socket<BUSWIDTH, TYPES, N, POL>